package com.ruoyi.datastatistics.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.basedata.domain.RedisKeyName;
import com.ruoyi.basedata.domain.TerminalsXb;
import com.ruoyi.basedata.domain.vo.TerminalsXbProtocol;
import com.ruoyi.basedata.service.ITerminalsXbService;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.CommonHelper;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.datastatistics.domain.MeterHistoryData;
import com.ruoyi.datastatistics.domain.Realtimegatherdata;
import com.ruoyi.datastatistics.domain.RealtimegatherdataXb;
import com.ruoyi.datastatistics.domain.parsevo.PacketForRedis;
import com.ruoyi.datastatistics.service.IGuoXincallBackService;
import com.ruoyi.datastatistics.service.IMeterHistoryDataService;
import com.ruoyi.datastatistics.service.IRealtimegatherdataXbService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 参数配置 服务层实现
 *
 * @author swdegao
 */
@Slf4j
@Service
public class GuoXincallBackServiceImpl implements IGuoXincallBackService {
    @Autowired
    private RedisCache redisCache;
    /*   @Autowired
       private CommonHelper commonHelper;*/
    @Autowired
    private ITerminalsXbService terminalsXbService;
    @Autowired
    private IRealtimegatherdataXbService realtimegatherdataXbService;
    @Autowired
    private IMeterHistoryDataService meterHistoryDataService;
    private static String factoryCode = "1002";

    @Override
    public void callBackSubscribe(String requestData,int sign) {

        if (!"".equals(requestData)) {
            PacketForRedis pr = nbIotpacketSaveTOJson(requestData,sign);
            if (pr != null && !pr.getJsonData().equals("")) {
                parsingMain(pr);
            }
        }

    }

    @Override
    public void insertCallBack(List<MeterHistoryData> list, TerminalsXbProtocol terminalsXb) {
        try {
            if (list.size() > 0) {
                try {
                    //历史数据插入到redis中
                    meterHistoryDataToRedisMain(list, terminalsXb);
                    //log.Info(terminalAdd+"历史数据插入到redis中");
                } catch (Exception e) {
                    log.error("历史数据插入到redis中异常" + e.getMessage());
                }
                try {
                    //更新设备、包括redis、数据库  去掉，数据库中表档案无需更新
                    synchronousMostValueFromRealtimegatherdata(list, terminalsXb);
                    //log.Info(terminalAdd+"更新设备、包括redis、数据库");
                } catch (Exception e) {
                    log.error("更新设备、包括redis、数据库异常" + e.getMessage());
                }
                try {
                    //将历史数据批量插入数据库
                    InsertMeterHistoryData(list, terminalsXb);
                    //log.Info(terminalAdd+"历史数据批量插入数据库");
                } catch (Exception e) {
                    log.error("历史数据批量插入数据库异常" + e.getMessage());
                }
                try {
                    removeRealtimeDataInRedis(terminalsXb);
                } catch (Exception e) {
                    log.error("removeRealtimeDataInRedis异常" + e.getMessage());
                }
            }


        } catch (Exception e) {
        }

    }

    public void meterHistoryDataToRedisMain(List<MeterHistoryData> list, TerminalsXbProtocol terminalsXb) throws ParseException {
        for (MeterHistoryData l : list) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Boolean flag2 = null;
            try {
                flag2 = checkIsSaveInRedis(terminalsXb.getCommunicateAddress(), sdf.parse(l.getReadDate()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            if (!flag2) {

                //插入到redis中
                redisCache.SortedSetAdd(RedisKeyName.backupDB_HistoricalData + factoryCode+"_" + terminalsXb.getCommunicateAddress(), l, ConvertDateTimeToInt(sdf.parse(l.getReadDate())));
            } else {
                list.remove(l);
            }
        }


    }

    public void parsingMain(PacketForRedis packetForRedis) {
        try {
            String packetType = packetForRedis.packetType;
            JSONArray json = new JSONArray();
            String terminalAdd = packetForRedis.getTerminalId();
            TerminalsXbProtocol terminalsXb = redisCache.getCacheMapValue(RedisKeyName.terminalInfo + factoryCode, terminalAdd);
            //跟据数据类型进行业务处理
            List<MeterHistoryData> list = new ArrayList<MeterHistoryData>();
            try {
                //历史数据插入到redis中
                meterHistoryDataToRedis(list, packetForRedis, terminalsXb);
                //log.Info(terminalAdd+"历史数据插入到redis中");
            } catch (Exception e) {
                log.error(packetForRedis.imei + "历史数据插入到redis中异常" + e.getMessage());
            }
            try {
                //更新设备、包括redis、数据库  去掉，数据库中表档案无需更新
                synchronousMostValueFromRealtimegatherdata(list, terminalsXb);
                //log.Info(terminalAdd+"更新设备、包括redis、数据库");
            } catch (Exception e) {
                log.error(packetForRedis.imei + "更新设备、包括redis、数据库异常" + e.getMessage());
            }
            try {
                //将历史数据批量插入数据库
                InsertMeterHistoryData(list, terminalsXb);
                //log.Info(terminalAdd+"历史数据批量插入数据库");
            } catch (Exception e) {
                log.error(packetForRedis.imei + "历史数据批量插入数据库异常" + e.getMessage());
            }
            try {
                removeRealtimeDataInRedis(terminalsXb);
            } catch (Exception e) {
                log.error(packetForRedis.imei + "removeRealtimeDataInRedis异常" + e.getMessage());
            }

        } catch (Exception e) {
        }

    }

    //历史数据插入到redis中
    public void meterHistoryDataToRedis(List<MeterHistoryData> list, PacketForRedis packetForRedis, TerminalsXbProtocol terminalsXb) {
        String errorflag = "200";
        try {
            JSONObject packet = packetForRedis.getJsonData();
            BigDecimal CumulantiveRate = new BigDecimal(1);
            errorflag = joiningTerminalpackage(list, packet, CumulantiveRate, terminalsXb);
            packetForRedis.actionStatus = errorflag;
            packetForRedis.insertime = ConvertDateTimeToInt(new Date());
            // redis.ListRightPush(RedisKeyName.InsertOver+ realtimeDetailDataForRedis.TerminalAddress, packetForRedis);
        } catch (Exception e) {
            errorflag = "508";//未知bug
            log.error("历史数据插入到redis 报错："+e.getMessage() + packetForRedis.toString());
            log.error(ExceptionUtil.getExceptionMessage(e));
        }
    }

    //历史数据插入到redis中
    public String joiningTerminalpackage(List<MeterHistoryData> list, JSONObject json, BigDecimal CumulantiveRate, TerminalsXb terminalsXb) throws ParseException {
        Boolean isAddRow = true;

        String flag = "200";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        //RedisHelp.RedisHelper redis = new RedisHelp.RedisHelper(1);
        if (json != null) {
            Date prevTime = null;
            BigDecimal prevTotalFlow = null;
            String date = json.getString("date");
            String date_ = getPackageDate(date);//返回格式年月日
            String type = json.getString("type");
            JSONArray info = json.getJSONArray("info");
            String voltage = json.getString("voltage");
            String valveStatus = json.getString("valveStatus");//阀门状态
            String signal1 = json.getString("signal1");
            String signal = json.getString("signal");
            String msgId = json.getString("msgId");

            for (int j = 0; j < info.size(); j++) {
                JSONObject temp_jo = info.getJSONObject(j);
                String time = temp_jo.getString("time");
                Integer num = Integer.parseInt(temp_jo.getString("num"));//本组中包含多少条数据
                Integer density = temp_jo.get("density") != null ? Integer.parseInt(temp_jo.getString("density")) : 15;//本组包获取密度
                time = getPackageTime(time, date_);//返回info中第一组time 得时间，格式年月日时分秒

                JSONArray dsinfo = temp_jo.getJSONArray("dsinfo");

                Date TerminalTime = null;
                try {
                    sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                    TerminalTime = sdf.parse(time);
                } catch (Exception e) {
                    flag = "501";
                    log.error(terminalsXb.getTerminalId() + "@@TerminalTime:" + e.getMessage());
                    continue;
                }


                if (TerminalTime == null)
                    continue;
                for (int k = 0; k < dsinfo.size(); k++) {
                    MeterHistoryData meterHistoryData = new MeterHistoryData();
                    try {
                        JSONObject job = dsinfo.getJSONObject(k);
                        isAddRow = true;

                        BigDecimal TotalFlow = null;
                        BigDecimal ReadNumber = null;
                        BigDecimal ReverseNumber = null;
                        BigDecimal InstantNumber = null;
                        BigDecimal Pressure = null;
                        BigDecimal InstantVelocity = null;

                        BigDecimal TerminalVol = null;
                        Integer TerminalCSQ = null;
                        try {
                            try {
                                meterHistoryData.setTotalFlow(job.get("TotalFlow") != null ? new BigDecimal(job.getString("TotalFlow")) : TotalFlow);
                                meterHistoryData.setReadNumber(job.get("ReadNumber") != null ? new BigDecimal(job.getString("ReadNumber")) : ReadNumber);
                                meterHistoryData.setReverseNumber(job.get("ReverseNumber") != null ? new BigDecimal(job.getString("ReverseNumber")) : ReverseNumber);
                            } catch (Exception e) {
                                log.error(terminalsXb.getTerminalId() + "@@流量解析异常" + e.getMessage());
                            }
                            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            meterHistoryData.setTenantId(terminalsXb.getTenantId());
                            meterHistoryData.setSupplierId(factoryCode);
                            meterHistoryData.setTerminalId(terminalsXb.getTerminalId());
                            meterHistoryData.setTerminalVol(json.get("voltage") != null ? new BigDecimal(json.getString("voltage")) : TerminalVol);
                            meterHistoryData.setTerminalCsq(!signal1.equals("") ? new Integer(signal1) : TerminalCSQ);
                            meterHistoryData.setValveState(new Integer(valveStatus));
                            meterHistoryData.setReadDate(sdf.format(TerminalTime));
                            meterHistoryData.setCreateDate(new Date());
                            meterHistoryData.setLocationNb(terminalsXb.getLocationNb());
                            //是否为机械大表
                            if ("1".equals(type) && CumulantiveRate != null) {
                                meterHistoryData.setTotalFlow(meterHistoryData.getTotalFlow().multiply(CumulantiveRate));
                            }
                        } catch (Exception e) {
                            flag = "502";
                            log.error(terminalsXb.getTerminalId() + "@@502" + e.getMessage());
                        }

                        //计算瞬时流量
                       /* if (null == realtimegatherdata.getReadNumber() && null == realtimegatherdata.getReverseNumber() && null == realtimegatherdata.getTotalFlow())
                        {
                            isAddRow = false;
                        }
*/
                        try {
                            if (true)
                            //  if (!realtimeDetailDataForRedis.ServerIndex1.HasValue || 0 == realtimeDetailDataForRedis.ServerIndex1.Value)
                            {
                                double d_TimeSpan = 0;//两条数据间时间间隔
                                /*try
                                {
                                    if (prevTime==null)
                                    {
                                        if (prevTotalFlow != null)
                                            realtimegatherdata.setInstantNumber( (realtimegatherdata.getTotalFlow().subtract(prevTotalFlow)).multiply(new BigDecimal(60)).divide(new BigDecimal(density)) );
                                    }
                                    else
                                    {
                                        d_TimeSpan = Math.abs((TerminalTime.getTime()-prevTime.getTime())/1000/60);//两条数据间时间间隔
                                        if (d_TimeSpan == density && prevTotalFlow != null)
                                            realtimegatherdata.setInstantNumber( (realtimegatherdata.getTotalFlow().subtract(prevTotalFlow)).multiply(new BigDecimal(60)).divide(new BigDecimal(density)) );

                                    }
                                }
                                catch (Exception e)
                                {
                                    flag = "504";
                                    log.error(terminalsXb.getTerminalID() + "@@504" + e.getMessage());
                                }*/
                                //对第一个瞬时流量点异常处理
                               /* if (j == 0 && k == 1 && Integer.parseInt(type) == 2 && list.size() > 0)//第一个点异常处理
                                {
                                    BigDecimal firstIns = list.get(0).getInstantNumber();
                                    if (firstIns != null)
                                    {
                                        try
                                        {
                                            BigDecimal secondIns = realtimegatherdata.getInstantNumber();
                                            if (secondIns.subtract(new BigDecimal(0)) != new BigDecimal(0) && firstIns.subtract(new BigDecimal(0)) != new BigDecimal(0))
                                            {
                                                //BigDecimal firstIns_ = firstIns.subtract(secondIns).abs().divide(secondIns).compareTo(new BigDecimal(0.05))>0? secondIns : firstIns;
                                                list.get(0).setInstantNumber(firstIns.subtract(secondIns).abs().divide(secondIns).compareTo(new BigDecimal(0.05))>0? secondIns : firstIns);
                                            }
                                            //针对与自主研发，第一个包的第一瞬时流量有问题，更新bykyx
                                            if (secondIns.compareTo(new BigDecimal(0)) == 0&& TotalFlow.compareTo(new BigDecimal(0)) == 0)
                                            {
                                                list.get(0).setInstantNumber(new BigDecimal(0));
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            flag = "503";
                                            log.error(terminalsXb.getTerminalID() + "@@++++++" + e.getMessage());
                                        }
                                    }
                                }*/
                            }
                        } catch (Exception e) {
                            flag = "508";
                            log.error(terminalsXb.getTerminalId() + "获取瞬时流量计算异常" + e.getMessage());
                        }


                        //每条数据中得冻结时间与数据包冻结时间对比，新协议中才有此时间newdate ->yyyy
                        String detailsTime = job.get("detailsTime") != null ? (!job.getString("detailsTime").equals("") ? new Date().toString().substring(0, 2) + job.getString("detailsTime") : "") : "";

                        //没有验证时间或者验证时间与数据包冻结时间相同
                        if ((!detailsTime.equals("") || detailsTime.equals(date_)) && isAddRow) {
                            Boolean flag2 = checkIsSaveInRedis(terminalsXb.getCommunicateAddress(), TerminalTime);
                            if (!flag2) {
                                list.add(meterHistoryData);
                                //插入到redis中
                                redisCache.SortedSetAdd(RedisKeyName.backupDB_HistoricalData + factoryCode+"_" + terminalsXb.getCommunicateAddress(), meterHistoryData, ConvertDateTimeToInt(TerminalTime));
                            }

                        } else {
                            //设备冻结时间不成功时，prevTotalFlow为零瞬时流量不进行计算 /20210515/kyx
                            prevTotalFlow = null;
                            flag = "505";
                            log.error("数据解析失败505-终端地址：" + terminalsXb.getTerminalId() + " detailsTime:" + detailsTime + " date_:" + date_ + " isAddRow:" + isAddRow);
                        }
                        //验证newdt中是否已经存在TerminalTime的数据2019-05-27
                        prevTime = TerminalTime;
                        prevTotalFlow = meterHistoryData.getTotalFlow();
                        TerminalTime = addMinutes(TerminalTime, density);
                    } catch (Exception e) {
                        flag = "506";
                        log.error(terminalsXb.getTerminalId() + "joiningTerminalpackage抛出异常：" + e.getMessage() + ExceptionUtil.getExceptionMessage(e));
                    }

                }
            }
        }
        return flag;
    }

    /**
     * 更新实时数据表
     *
     * @param list
     * @param terminalsXb
     */
    public void synchronousMostValueFromRealtimegatherdata(List<MeterHistoryData> list, TerminalsXbProtocol terminalsXb) throws ParseException {

        if (list.size() > 0) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            RealtimegatherdataXb realtimegatherdata = new RealtimegatherdataXb();
            realtimegatherdata.setLocationNb(terminalsXb.getLocationNb());
            List<RealtimegatherdataXb> isupate = realtimegatherdataXbService.selectRealtimegatherdataXbList(realtimegatherdata);

            MeterHistoryData t = list.get(list.size() - 1);
            realtimegatherdata.setTenantId(terminalsXb.getTenantId());
            realtimegatherdata.setTerminalId(terminalsXb.getTerminalId());
            realtimegatherdata.setTotalFlow(t.getTotalFlow());
            realtimegatherdata.setTerminalCsq(t.getTerminalCsq());
            realtimegatherdata.setTerminalVol(t.getTerminalVol());
            realtimegatherdata.setLocationNb(terminalsXb.getLocationNb());
            if (t.getValveState() != null) {
                realtimegatherdata.setValveState(new BigDecimal(t.getValveState()));
            }
            realtimegatherdata.setReadDate(sdf.parse(t.getReadDate()));
            realtimegatherdata.setCreateTime(new Date());

            if (isupate.size() > 0) {
                //更新
                realtimegatherdataXbService.updateRealtimegatherdataXb(realtimegatherdata);
            } else {
                //插入
                realtimegatherdataXbService.insertRealtimegatherdataXb(realtimegatherdata);
            }
        }
    }

    /**
     * 时间添加
     *
     * @param date
     * @param minutes
     * @return
     */
    public static Date addMinutes(Date date, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
    }

    /// <summary>
    /// 是否再redis中存储，false没有存储，true已经存储
    /// </summary>
    /// <param name="terminaladd"></param>
    /// <param name="stratTime"></param>
    /// <returns></returns>
    public Boolean checkIsSaveInRedis(String terminaladd, Date stratTime) {
        Boolean flag = false;

        Set<Realtimegatherdata> list = redisCache.SortedSetRangeByRank(RedisKeyName.backupDB_HistoricalData + factoryCode+"_" + terminaladd, ConvertDateTimeToInt(stratTime), ConvertDateTimeToInt(stratTime));
        if (null != list && list.size() > 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 时间处理
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public String getPackageDate(String date) throws ParseException {
        String date_ = "";//时间 临时
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        if (!date.equals(""))
            date_ = date.length() > 4 ? sdf.format(new Date()).substring(0, 2) + date : sdf.format(new Date()) + date;
        sdf = new SimpleDateFormat("yyyyMMdd");
        Date dt = sdf.parse(date_);

        if (dt.compareTo(new Date()) > 0) {
            String year = new Date().getYear() - 1 + "";
            date = date.length() > 4 ? date_ : year + date;

        } else {
            date = date_;
        }
        return date;
    }

    /**
     * 时间处理
     *
     * @param time
     * @param date
     * @return
     */
    public String getPackageTime(String time, String date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        time = time.length() < 2 ? "0" + time : time;
        time = time.length() < 4 ? (date + time + "0000") : sdf.format(new Date()).substring(0, 2) + time + "00";
        return time;
    }

    /// <summary>
    /// 插入日冻结数据
    /// </summary>
    /// <param name="dt"></param>
    /// <param name="con"></param>
    /// <returns></returns>
    public boolean InsertMeterHistoryData(List<MeterHistoryData> list, TerminalsXb terminalsXb) {
        boolean copy = false;
        if (list.size() > 0) {
            meterHistoryDataService.batchinsertMeterHistoryData(list);
            //realtimegatherdataXbService.batchinsertRealtimegatherdataXb(list);
            copy = true;
        }

        return copy;
    }

    /// <summary>
    /// 清理redis中数据
    /// </summary>
    /// <param name="terminalAdd"></param>
    public void removeRealtimeDataInRedis(TerminalsXb terminalsXb) {
        try {
            Set<Realtimegatherdata> firt_list = redisCache.SortedSetRangeByRank(RedisKeyName.backupDB_HistoricalData+factoryCode+"_" + terminalsXb.getCommunicateAddress(), 0, 0);

            if (firt_list != null && firt_list.size() > 0) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Long interval = new Date().getTime() - sdf.parse(firt_list.stream().findFirst().get().getTerminalTime()).getTime();
                if (interval / (24 * 60 * 60 * 1000) > RedisKeyName.backupDB_HistoricalData_days) {
                    long st = new Date().getTime() - RedisKeyName.backupDB_HistoricalData_days * (24 * 60 * 60 * 1000);
                    redisCache.SortedSetRemoveByScore(RedisKeyName.backupDB_HistoricalData+factoryCode+"_" + terminalsXb.getCommunicateAddress(), sdf.parse(firt_list.stream().findFirst().get().getTerminalTime()).getTime(), st);

                }
            }


        } catch (Exception e) {
            log.error(terminalsXb.getTerminalId() + "历史数据清理异常" + e.getMessage());
        }
    }

    /// <summary>
    /// 将NB传过来的值解析成json存储到redis中
    /// </summary>
    /// <param name="data"></param>
    /// <param name="terminalAdd"></param>
    public PacketForRedis nbIotpacketSaveTOJson(String requestData,int sign) {
        String terminalAdd = "";
        PacketForRedis packetForRedis = new PacketForRedis();
        try {
            // var jo_ = JsonConvert.DeserializeObject(requestData);
            JSONObject jo = JSONObject.parseObject(requestData);
            byte[] data = null;
            String data_ = null;
            String imei = null;
            String deviceId = null;
            if (sign==1){
                data_ = jo.getJSONObject("payload").getString("APPdata");
                // data = Base64.getDecoder().decode(data_);
                //data = hexStringToByteArray(data_);
                data = hexStringToByteArray(data_);
                imei = jo.getString("IMEI");
                //terminalAdd = getTerminalAdd(data);//截取地址
                deviceId = jo.getString("deviceId");
            }
            if (sign==2){
                JSONObject onenet  = jo.getJSONObject("msg");
                data_ = onenet.getString("body");
                data = hexStringToByteArray(data_);
                imei = jo.getJSONObject("msg").getString("imei");
                deviceId = jo.getJSONObject("msg").getJSONObject("appProperty").getString("deviceId");
            }
            //获取设备基础信息，获取属性协议
            String aClassName = "";
            TerminalsXbProtocol terminalsXb = new TerminalsXbProtocol();
            terminalsXb.setImei(imei);

            //走UDP通讯方式
            if (sign==3){
                deviceId = jo.getString("imei");
                if(jo.get("upDataList") != null){
                    data_ = jo.getJSONArray("upDataList").getJSONObject(0).getString("upData");
                    data = hexStringToByteArray(data_);
                    imei = jo.getString("imei");
                    terminalAdd = imei;
                    terminalsXb = new TerminalsXbProtocol();
                    //获取设备基础信息，获取属性协议
                    terminalsXb.setTerminalId(imei);
                }
            }
            List<TerminalsXbProtocol> listXb = terminalsXbService.selectTerminalsXbProtocolList(terminalsXb);
            if (listXb.isEmpty()) {
                return null;
            }
            terminalsXb = listXb.get(0);

            try {
                if (!redisCache.hmhave(RedisKeyName.terminalInfo + factoryCode, terminalsXb.getCommunicateAddress()))//redis中是否存在该设备
                {

                    // terminalsXb = terminalsXbService.selectTerminalsXbProtocolList(terminalsXb).get(0);
                    if (terminalsXb != null) {
                        //RealtimeDetailDataForRedis = getRealtimeDetailDataForRedis(terminalAdd);
                        redisCache.setCacheMapValue(RedisKeyName.terminalInfo + factoryCode, terminalsXb.getCommunicateAddress(), terminalsXb);
                        aClassName = terminalsXb.getClassName();
                    } else {
                        //若是数据库里查找不到档案，记录到解析日志表中
                        redisCache.lPush(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, requestData);//记录异常
                    }
                } else {
                    terminalsXb = redisCache.getCacheMapValue(RedisKeyName.terminalInfo + factoryCode, terminalsXb.getCommunicateAddress());
                    aClassName = terminalsXb.getClassName();
                }
            } catch (Exception e) {
                redisCache.lPush(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, requestData);//记录异常
                redisCache.trim(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, -4, -1);//删除exceptions数据

                return null;
            }
            if ("".equals(aClassName) || aClassName == null) aClassName = "com.ruoyi.datastatistics.Agreement.GuoXinV1";
            //解析成json,存储到redis
            Object param = data;
            JSONObject temp = getPacketForRedis(data, aClassName);
            int packetType = data[9];
            packetForRedis = new PacketForRedis();
            packetForRedis.imei = deviceId;
            packetForRedis.packetType = packetType + "";
            packetForRedis.jsonData = temp;
            packetForRedis.nettycreatetime = ConvertDateTimeToInt(new Date());
           // packetForRedis.setTerminalId(terminalsXb.getCommunicateAddress());
            packetForRedis.setTerminalId(terminalsXb.getTerminalId());
            // redisCache.lPush(RedisKeyName.WaitingPacketInsert + terminalAdd, packetForRedis);
        } catch (Exception e) {
            redisCache.lPush(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, requestData);//记录异常
            redisCache.trim(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, -4, -1);//删除exceptions数
        }
        return packetForRedis;
    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    private JSONObject getPacketForRedis(byte[] data, String aClassName) {
        JSONObject jo = new JSONObject();
        Object[] param = {data};
        if ((byte) data[8] == 0x04) {
            Object temp = CommonHelper.getMethod(aClassName, "GetBufferPacketForAll", param);
            jo = (JSONObject) temp;

        }
        if ((byte) data[0] == -17) {
            Object temp = CommonHelper.getMethod(aClassName, "GetBufferPacketForAll", param);
            jo = (JSONObject) temp;
        }
        return jo;
    }

    /**
     * DateTime时间格式转换为Unix时间戳格式
     *
     * @param time
     * @return
     */
    public long ConvertDateTimeToInt(Date time) {
        long timeInMillis = time.getTime();
        long unixTime = timeInMillis / 1000;
        return unixTime;
    }

    private byte[] hexStringToByte(String hex) {
        int len = (hex.length() / 2); //除以2是因为十六进制比如a1使用两个字符代表一个byte
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            //乘以2是因为十六进制比如a1使用两个字符代表一个byte,pos代表的是数组的位置
            //第一个16进制数的起始位置是0第二个是2以此类推
            int pos = i * 2;
            //<<4位就是乘以16  比如说十六进制的"11",在这里也就是1*16|1,而其中的"|"或运算就相当于十进制中的加法运算
            //如00010000|00000001结果就是00010001 而00010000就有点类似于十进制中10而00000001相当于十进制中的1，与是其中的或运算就相当于是10+1(此处说法可能不太对，)
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }

    private byte toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * 获取设备地址
     *
     * @param bit
     * @return
     */
    private String getTerminalAdd(byte[] bit) {
        byte[] bit_add = new byte[4];
        System.arraycopy(bit, 5, bit_add, 0, 4);
        int temp = Integer.parseInt(getIntFromByte2(bit_add));//终端地址
        return temp + "";
    }

    /**
     * 两位不足 补零,高位在hou,eg->0x0c 0x02:0c02
     *
     * @param bit
     * @return
     */
    public static String getIntFromByte2(byte[] bit) {
        String str = "";
        for (int i = 0; i < bit.length; i++) {
            String temp = Integer.toHexString(bit[i] & 0xFF);
            temp = temp.length() < 2 ? ("0" + temp) : temp;
            str = str + temp;
        }
        return str;
    }


    public static void main(String[] args) {
        byte[] data = hexStringToByteArray("C041164309103356040100000000000000000113000300000001280000153E05615A01400A91CD132D0000E90200B900001401D4000A00D8635601FFFFFFFF000000000221240801006805010068050100680501002408010000000000000000000000000000031100000000000000000000000000000000000998003005613C00484200000000000037000F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000210000000000E1D0");
        GuoXincallBackServiceImpl service = new GuoXincallBackServiceImpl();
        JSONObject temp = service.getPacketForRedis(data, "com.ruoyi.datastatistics.Agreement.GuoXinV1");
        System.out.println(JSONUtil.toJsonStr(temp));
    }
}
